package cn.laixueit.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.laixueit.base.R;
import cn.laixueit.pojo.BookChapter;
import cn.laixueit.pojo.BookChapterContent;
import cn.laixueit.service.BookChapterContentService;
import cn.laixueit.service.BookChapterService;
import cn.laixueit.utils.CalculateUtils;
import cn.laixueit.utils.CodeUtils;
import cn.laixueit.vo.BookVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import cn.laixueit.pojo.Book;
import cn.laixueit.service.BookService;
import cn.laixueit.mapper.BookMapper;
import com.github.yulichang.base.MPJBaseServiceImpl;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;

/**
 *
 */
@Service
public class BookServiceImpl extends MPJBaseServiceImpl<BookMapper, Book>
    implements BookService{

    @Resource
    private CodeUtils codeUtils;
    @Resource
    private BookChapterService bookChapterService;
    @Resource
    private BookChapterContentService bookChapterContentService;
    @Resource
    private CalculateUtils<Book,BookVo> calculateUtils;

    @Override
    public R listPage(Page<Book> pageInfo, BookVo bookvo) {
        QueryWrapper<Book> wrapper = new QueryWrapper<>();
        wrapper.lambda().orderByDesc();
        Page<Book> bookPage = page(pageInfo, wrapper);
        ArrayList<BookVo> bookVos = new ArrayList<>();
        List<Book> records = bookPage.getRecords();
        records.forEach(x -> {
            BookVo vo = new BookVo();
            vo = calculateUtils.calculateNewPrice(x, vo);
            bookVos.add(vo);
        });

        return R.ok().put("total", bookPage.getTotal()).put("rows", bookVos);
    }

    @Override
    public void saveOrUpdateBook(Book book) {
        if(StringUtils.isBlank(book.getCode())){
            String code = codeUtils.getNewCode("code","tb_book");
            book.setCode(code);
        }
        saveOrUpdate(book);
    }

    /**
     * 获取书籍及其所有章节及第一章节的内容
     * @param id
     * @param chapterId
     * @return
     */
    @Override
    public BookVo getRowAndChapter(String id, String chapterId) {
        MPJLambdaWrapper<Book> wrapper = new MPJLambdaWrapper<Book>();
        wrapper.selectAll(Book.class)
                .selectCollection(BookChapter.class,Book::getChapterList)
                .leftJoin(BookChapter.class,BookChapter::getCode,Book::getCode,qr->qr.orderByAsc(BookChapter::getSort))
                .eq(Book::getId,id);
        Book book = selectJoinOne(Book.class, wrapper);
//        books.stream().forEach(x->{
            BookVo vo = new BookVo();
            vo = calculateUtils.calculateNewPrice(book, vo);
//        });
        LinkedList<BookChapter> chapterList = vo.getChapterList();
        if(CollectionUtil.isNotEmpty(chapterList)) {
            String cId = chapterId;
            if (StringUtils.isBlank(chapterId)) {
                cId = chapterList.get(0).getId();
            }
            BookChapterContent content = this.getContent(cId);
            vo.setContent(content);
        }
        return vo;
    }

    /**
     * 保存书籍和章节
     * @param book
     */
    @Override
    @Transactional
    public void saveAndChapter(Book book) {
        this.saveOrUpdateBook(book);
        LinkedList<BookChapter> chapterList = book.getChapterList();

//        bookChapterService.remove(bookChapterService.lambdaQuery().eq(BookChapter::getCode,book.getCode()).getWrapper());

        AtomicInteger sortIndex = new AtomicInteger(1);
        chapterList.stream().map(x->{
            sortIndex.getAndIncrement();
            if(ObjectUtil.isEmpty(x.getSort())){
                x.setSort(sortIndex.get());
            }
            return x;
        }).sorted(Comparator.comparing(BookChapter::getSort)).forEach(x-> {
//            x.setSort(sortIndex.getAndIncrement());
            x.setCode(book.getCode());
        });
        bookChapterService.saveOrUpdateBatch(chapterList,1000);
    }

    /**
     * 缠结id
     * @param id
     * @return
     */
    @Override
    public BookChapterContent getContent(String id) {
        BookChapterContent content = bookChapterContentService.getOne(bookChapterContentService.lambdaQuery()
                .eq(BookChapterContent::getChapterId,id)
                .getWrapper());
        return content;
    }

    /**
     * 保存章节内容
     * @param chapterContent
     */
    @Override
    public void saveContent(BookChapterContent chapterContent) {
        Optional.ofNullable(chapterContent.getChapterId()).ifPresent(x->{
            BookChapterContent content = bookChapterContentService.getOne(bookChapterContentService.lambdaQuery()
                    .eq(BookChapterContent::getChapterId,chapterContent.getChapterId())
                    .getWrapper());
            chapterContent.setId(content.getId());
        });
        bookChapterContentService.saveOrUpdate(chapterContent);
    }

    @Override
    @Transactional
    public void removeChapterAndContent(String id) {
        bookChapterService.removeById(id);
        bookChapterContentService.remove(Wrappers.<BookChapterContent>lambdaQuery().eq(BookChapterContent::getChapterId,id));
    }

    @Override
    public BookChapter saveChapter(BookChapter chapter) {
        if(ObjectUtil.isEmpty(chapter.getSort())){
            List<BookChapter> chapterList = bookChapterService.list(bookChapterService.lambdaQuery().eq(BookChapter::getCode,chapter.getCode()).orderByDesc(BookChapter::getSort).getWrapper());
            Integer sort = chapterList.get(0).getSort();
            chapter.setSort(sort+1);
        }
        bookChapterService.saveOrUpdate(chapter);
        return chapter;
    }

    @Override
    public Book listBookAndChaptersAndContents(String id) {
        MPJLambdaWrapper<Book> wrapper = new MPJLambdaWrapper<Book>();
        wrapper.selectAll(Book.class)
                .selectCollection(BookChapter.class,Book::getChapterList,qr->qr.association(BookChapterContent.class,BookChapter::getBookChapterContent))
                .leftJoin(BookChapter.class,BookChapter::getCode,Book::getCode,qr->qr.orderByAsc(BookChapter::getSort))
                .leftJoin(BookChapterContent.class,BookChapterContent::getChapterId,BookChapter::getId)
                .eq(Book::getId,id);
        Book book = selectJoinOne(Book.class, wrapper);
        return book;
    }

    @Override
    public R listBookAndOneChapters(BookVo bookvo) {
        List<Book> bookList = list(lambdaQuery().like(StringUtils.isNotBlank(bookvo.getName()),Book::getName,bookvo.getName())
                .orderByAsc(Book::getSort,Book::getCreateTime).getWrapper()
        );
        /*if(CollectionUtil.isNotEmpty(bookList)){
            Book book = bookList.get(0);
            BookVo bookVo = getRowAndChapter(book.getId(), null);
            return R.ok().put("rows",bookList).put("chapters",bookVo.getChapterList());
        }*/
        return R.ok().put("rows",bookList);
    }

    /**
     * 获取书籍的所有章节
     *
     * @param chapterPage
     * @param chapter
     * @return
     */
    @Override
    public R chapterList(Page<BookChapter> chapterPage, BookChapter chapter) {
        Page<BookChapter> page = bookChapterService.page(chapterPage, bookChapterService.lambdaQuery()
                .eq(BookChapter::getCode, chapter.getCode())
                .like(StringUtils.isNotBlank(chapter.getName()),BookChapter::getName,chapter.getName())
                .getWrapper());
        return R.ok().put("rows",page.getRecords());
    }

    @Override
    public R chapterContent(String id) {
//        MPJLambdaWrapper<BookChapter> wrapper = new MPJLambdaWrapper<>();
//        wrapper.selectAll(BookChapter.class)
//                .selectAssociation(BookChapterContent.class,BookChapter::getBookChapterContent)
//                .leftJoin(BookChapterContent.class,BookChapterContent::getChapterId,BookChapter::getId)
//                .eq(BookChapter::getId,id);
//        BookChapter bookChapter = bookChapterService.selectJoinOne(BookChapter.class, wrapper);
        BookChapterContent content = bookChapterContentService.getOne(bookChapterContentService.lambdaQuery()
                .eq(BookChapterContent::getChapterId,id)
                .getWrapper());
        return R.ok().put("obj",content);
    }
}




